use <scad-utils/transformations.scad>
use <scad-utils/lists.scad>

// Skin a set of profiles with a polyhedral mesh
module skin(profiles, loop=false /* unimplemented */) {
  P = max_len(profiles);
  N = len(profiles);

  profiles = [
    for (p = profiles)
      for (pp = augment_profile(to_3d(p),P))
        pp
  ];

  function quad(i,P,o) = [[o+i, o+i+P, o+i%P+P+1], [o+i, o+i%P+P+1, o+i%P+1]];

  function profile_triangles(tindex) = [
    for (index = [0:P-1])
      let (qs = quad(index+1, P, P*(tindex-1)-1))
        for (q = qs) q
  ];

    triangles = [
    for(index = [1:N-1])
          for(t = profile_triangles(index))
        t
  ];

  start_cap = [range([0:P-1])];
  end_cap   = [range([P*N-1 : -1 : P*(N-1)])];

  polyhedron(convexity=2, points=profiles, faces=concat(start_cap, triangles, end_cap));
}

// Augments the profile with steiner points making the total number of vertices n
function augment_profile(profile, n) =
  subdivide(profile,insert_extra_vertices_0([profile_lengths(profile),dup(0,len(profile))],n-len(profile))[1]);

function subdivide(profile,subdivisions) = let (N=len(profile)) [
  for (i = [0:N-1])
    let(n = len(subdivisions)>0 ? subdivisions[i] : subdivisions)
      for (p = interpolate(profile[i],profile[(i+1)%N],n+1))
        p
];

function interpolate(a,b,subdivisions) = [
  for (index = [0:subdivisions-1])
    let(t = index/subdivisions)
      a*(1-t)+b*t
];

function distribute_extra_vertex(lengths_count,ma_=-1) = ma_<0 ? distribute_extra_vertex(lengths_count, max_element(lengths_count[0])) :
  concat([set(lengths_count[0],ma_,lengths_count[0][ma_] * (lengths_count[1][ma_]+1) / (lengths_count[1][ma_]+2))], [increment(lengths_count[1],max_element(lengths_count[0]),1)]);

function insert_extra_vertices_0(lengths_count,n_extra) = n_extra <= 0 ? lengths_count :
  insert_extra_vertices_0(distribute_extra_vertex(lengths_count),n_extra-1);

// Find the index of the maximum element of arr
function max_element(arr,ma_,ma_i_=-1,i_=0) = i_ >= len(arr) ? ma_i_ :
  i_ == 0 || arr[i_] > ma_ ? max_element(arr,arr[i_],i_,i_+1) : max_element(arr,ma_,ma_i_,i_+1);

function max_len(arr) = max([for (i=arr) len(i)]);

function increment(arr,i,x=1) = set(arr,i,arr[i]+x);

function profile_lengths(profile) = [
  for (i = [0:len(profile)-1])
    profile_segment_length(profile,i)
];

function profile_segment_length(profile,i) = norm(profile[(i+1)%len(profile)] - profile[i]);

// Generates an array with n copies of value (default 0)
function dup(value=0,n) = [for (i = [1:n]) value];







use <scad-utils/transformations.scad>
use <scad-utils/trajectory_path.scad>
use <scad-utils/trajectory.scad>
use <scad-utils/shapes.scad>

module fakeISOEnter(thickness_difference = 0){
    // 1u is the space taken upy by a 1u keycap.
    // unit is the space taken up by a unit space for a keycap.
    // formula is 1u + unit *(length - 1)

    // t is all modifications to the polygon array
    t = thickness_difference/2 - (19.02 - 18.16);

    function unit(length) = 19.02 * length;

    pointArray = [
        [19.05 * (-.5)  + t,      19.05 * (-1)  + t],
        [19.05 * (0.5)  - t,      19.05 * (-1)  + t],
        [19.05 * (0.5)  - t,      19.05 * (1)  - t],
        [19.05 * (-0.75) + t,      19.05 * (1)  - t],
        [19.05 * (-0.75) + t,      19.05 * (0)  + t],
        [19.05 * (-0.5) + t,      19.05 * (0)  + t]
    ];


  /*translate([unit(-.5), unit(-1) + 0.86]){*/
    minkowski() {
            circle($corner_radius, $fn=20);
            offset(r=-$corner_radius * 2, $fn=20) polygon(points=pointArray);
          }
  /*}*/
}

function isoEnter() = [
        [19.05 * (-.5)  + (19.02 - 18.16),      19.05 * (-1)  + (19.02 - 18.16)],
        [19.05 * (0.5)  - (19.02 - 18.16),      19.05 * (-1)  + (19.02 - 18.16)],
        [19.05 * (0.5)  - (19.02 - 18.16),      19.05 * (1)  - (19.02 - 18.16)],
        [19.05 * (-0.75) + (19.02 - 18.16),      19.05 * (1)  - (19.02 - 18.16)],
        [19.05 * (-0.75) + (19.02 - 18.16),      19.05 * (0)  + (19.02 - 18.16)],
        [19.05 * (-0.5) + (19.02 - 18.16),      19.05 * (0)  + (19.02 - 18.16)]
    ];


path_definition = [
trajectory(forward = 10, roll  =  0),
];

// sweep
path = quantize_trajectories(path_definition, steps=100);

// skin
myLen = len(path)-1;
trans = [ for (i=[0:len(path)-1]) transform(path[i], isoEnter()) ];

translate([0,10,0])
  skin(trans);
